/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.mocking;

import picounit.Registry;
import picounit.Should;
import picounit.When;
import picounit.features.Feature;
import picounit.features.base.FeatureRegistry;
import picounit.features.base.ProxyFactory;
import picounit.features.constraint_store.ConstraintStore;
import picounit.mocker.MockControl;
import picounit.mocker.MockFactory;
import picounit.mocker.OccurencesMatcher;

public class MockingFeature implements Feature {
	private final ConstraintStore constraintStore;
	private final ReturnTypeModifier returnTypeModifier;
	private final Registry registry;

	public MockingFeature(ConstraintStore constraintStore, ReturnTypeModifier returnTypeModifier,
		Registry registry) {
		
		this.constraintStore = constraintStore;
		this.returnTypeModifier = returnTypeModifier;
		this.registry = registry;
	}
	
	public void addFeatures(FeatureRegistry featureRegistry) {
		MockInvocationObserver mockInvocationObserver = new MockInvocationObserver();
		featureRegistry.addFeatures(mockInvocationObserver);

		OccurencesMatcherImpl occurencesMatcherImpl = new OccurencesMatcherImpl();
		OccurencesMatcher occurencesMatcher = occurencesMatcherImpl;
		ActiveRecordingPlaybackMock activeRecordingPlaybackMock = occurencesMatcherImpl;
		RecordingPlaybackMockListener recordingPlaybackMockListener = occurencesMatcherImpl;

		ProxyFactory proxyFactory = new ProxyFactory();
		
		JMocker mocker = new JMocker(
		occurencesMatcher,
		activeRecordingPlaybackMock,
		recordingPlaybackMockListener,
		mockInvocationObserver, 
		proxyFactory, 
		returnTypeModifier,
		constraintStore);

		registry.register(Should.class, mocker);
		registry.register(MockControl.class, mocker.mockControl());
		registry.register(MockFactory.class, mocker.mockFactory());

		registry.register(When.class, new Stubber(
			new ArrayStubber(
				combinedArrayConsequenceMatcher(mockInvocationObserver, occurencesMatcherImpl),
				mocker), combinedConsequenceMatcher(mockInvocationObserver, occurencesMatcherImpl),
			mocker)); 

		featureRegistry.addFeatures(proxyFactory, mocker, mocker.mockControl(), mocker.mockFactory(),
			mocker.typeFactory());
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	// Implementation methods
	///////////////////////////////////////////////////////////////////////////////////////////////

	private CombinedConsequenceMatcher combinedConsequenceMatcher(
		MockInvocationObserver mockInvocationObserver, OccurencesMatcherImpl occurencesMatcherImpl) {

		return new CombinedConsequenceMatcher(occurencesMatcherImpl, occurencesMatcherImpl,
			mockInvocationObserver);
	}

	private CombinedArrayConsequenceMatcher combinedArrayConsequenceMatcher(
		MockInvocationObserver mockInvocationObserver, OccurencesMatcherImpl occurencesMatcherImpl) {

		return new CombinedArrayConsequenceMatcher(occurencesMatcherImpl, occurencesMatcherImpl,
			mockInvocationObserver);
	}
}
